package com.depth.viewer.facade
{
	import com.depth.viewer.events.AppEvent;
	import com.depth.viewer.manager.IWidgetManager;
	import com.depth.viewer.manager.IWidgetRegistry;
	import com.depth.viewer.manager.ViewerSystemManager;
	import com.depth.viewer.utils.Util;
	import com.depth.viewer.widget.IBaseWidget;
	import com.depth.viewer.widget.definition.IWidgetDefinition;
	
	import flash.events.Event;
	import flash.text.StaticText;
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	
	import org.puremvc.as3.patterns.facade.Facade;
	import org.springextensions.actionscript.context.support.XMLApplicationContext;
	import org.springextensions.actionscript.puremvc.patterns.facade.IocFacade;
	import org.springextensions.actionscript.utils.ObjectUtils;
	
	public class IocAppFacade extends IocFacade 
	{
		
		public static const CONFIG_LOADED:String = "configLoaded";
		public static const WIDGET_CONFIG_LOADED:String = "widgetConfigLoaded";
		
		public static const WIDGET_LOADED:String = "widgetLoaded";
		public static const WIDGET_REMOVED:String = "widgetRemoved";
		public static const WIDGET_UNLOADED:String = "widgetUnloaded";
		
		public static const LOAD_WIDGET:String = "loadWidget";
		public static const REMOVE_WIDGET:String = "removeWidget";
		public static const UNLOAD_WIDGET:String = "unloadWidget";
		public static const RE_LOAD_WIDGET:String = "reLoadWidget";
		public static const SET_WIDGET_STATE:String = "setWidgetState";
		
		private var _lookupObjects:ArrayCollection = new ArrayCollection();
		
		private static var instance:IocAppFacade;
		
		public static function get debug():Boolean{
			return Util.getParams().debug;
		}
		
		[Bindable]
		private var _map:Object;
		public function set map(value:Object):void{
			
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgets:Array = rg.getRegistedWidgets();
			for each(var widget:IBaseWidget in widgets){
				widget.map = value;
			}
			this._map = value;
		}
		public function get map():Object{
			return this._map;
		}
		
		private var _widgetManager:IWidgetManager;
		
		public function IocAppFacade(key:String,p_configSource:* = null)
		{
			super(key,p_configSource);
		}
		public static function  getInstance():IocAppFacade
		{
			if(instance == null){
				instance = new IocAppFacade("app");
			}
			return instance as IocAppFacade;
		}
		override protected function onObjectFactoryListenerComplete(p_event:Event):void{
			super.onObjectFactoryListenerComplete(p_event);
			_widgetManager = ViewerSystemManager.getInstance().widgetManager;
			ViewerSystemManager.getInstance().dispatchEvent(new AppEvent(AppEvent.CONFIG_LOADED));
		}
		public function getObject(name:String):Object{
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgetDefs:Array = 	rg.getRegistedWidgetDefinitions();
			
			try{
				var o:Object = getInstance().container.getObject(name);
				if(o){
					return o;
				}
			}catch(err:Error){
				
			}
			
			for each(var widgetDef:IWidgetDefinition in widgetDefs){
				if(widgetDef.context){
					try{
						var obj:Object = widgetDef.context.getObject(name);
						if(obj){
							return obj;
						}
					}catch(err:Error){
						continue;
					}
				}
			}
			return null;
		}
		public function getObjectOfType(type:Class):Object{
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgetDefs:Array = 	rg.getRegistedWidgetDefinitions();
			
			try{
				var obj:Object;
				var objectNames:Array = getObjectNamesForType(type);
				if(objectNames.length > 0){
					var objName:String = objectNames[0];
					obj = getObject(objName);
				}
				if(obj){
					return obj;
				}
			}catch(err:Error){
				trace(err.message);
				trace(err.getStackTrace());
			}
			return null;
		}
		public function getObjectsOfType(type:Class):Array{
			var objects:Array = [];
			var objectNames:Array = getObjectNamesForType(type);
			for each(var objName:String in objectNames){
				var obj:Object = getObject(objName);
				objects.push(obj);
			}
			return objects;
		}
		public function getObjectNamesForType(type:Class):Array{
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgetDefs:Array = 	rg.getRegistedWidgetDefinitions();
			
			var names:Array = [];
			var appNames:Array = getInstance().container.getObjectNamesForType(type);
			
			Util.connect(names,appNames);
			
			for each(var widgetDef:IWidgetDefinition in widgetDefs){
				if(widgetDef.context){
					var widgetNames:Array = widgetDef.context.getObjectNamesForType(type);
					names = names.concat(widgetNames);
				}
			}
			return names;
		}
		public function getContext(bundleId:String):XMLApplicationContext{
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgetDef:IWidgetDefinition = rg.getRegistedWidgetDefinition(bundleId);
			if(!widgetDef){
				throw new Error("未注册的widget:" + bundleId);
			}
			return widgetDef.context;
		}
		
		public function getWidgetFacade(widgetId:String):IWidgetFacade{
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgetDef:IWidgetDefinition = rg.getRegistedWidgetDefinition(widgetId);
			if(!widgetDef){
				throw new Error("未注册的widget:" + widgetId);
			}
			return widgetDef.facade as IWidgetFacade;
		}
		
		
		
		public function lookup(type:Class):Array{
			var objs:Array = [];
			for each(var obj:Object in _lookupObjects){
				if(obj is type){
					objs.push(obj);
				}
			}
			var contextObjects:Array =  getObjectsOfType(type);
			Util.connect(objs,contextObjects);
			
			var rg:IWidgetRegistry = _widgetManager.getRegistry().getRegistry();
			var widgetDefs:Array = 	rg.getRegistedWidgetDefinitions();
			
			for each(var widgetDef:IWidgetDefinition in widgetDefs){
				var widgetFacade:IWidgetFacade = widgetDef.facade as IWidgetFacade;
				var widgetLookupOjbects:Array = widgetFacade.lookup(type);
				Util.connect(objs,widgetLookupOjbects);
			}
			return objs;
		}
		
		public function addObjectToContextObject(id:String,object:Object):void{
			try{
				var contextObject:Dictionary = IocAppFacade.getInstance().getObject("contextObject") as Dictionary;
				if(contextObject){
					contextObject[id] = object;
				}
			}catch(err:Error){
				trace(err.getStackTrace());
			}
		}
		public function getObjectFromContextObject(id:String):Object{
			try{
				var contextObject:Dictionary = IocAppFacade.getInstance().getObject("contextObject") as Dictionary;
				if(contextObject){
					return contextObject[id];
				}
			}catch(err:Error){
				trace(err.getStackTrace());
				return  null;
			}	
			return null;
		}
		public function addObject(object:Object):void{
			//判断上下文中是否有此实例
			var sameTypeObjects:Array = getObjectsOfType(ObjectUtils.getClass(object));
			for each(var obj:Object in sameTypeObjects){
				if(object == obj){
					return;
				}
			}
			//判断是否己存在
			var existentObject:Object;
			for each(var obj:Object in _lookupObjects){
				if(obj == object){
					existentObject = obj;
				}
			}
			if(existentObject){
				return;
			}
			_lookupObjects.addItem(object);
		}
		public 	function removeObjectByType(type:Class):void{
			for each(var obj:Object in _lookupObjects){
				if(obj is type){
					removeObject(obj);
				}
			}
		}
		public function removeObject(object:Object):void{
			var index:int = _lookupObjects.getItemIndex(object);
			if(index != -1){
				_lookupObjects.removeItemAt(index);
			}
		}
		
		public static function reset():void{
			Facade.removeCore("app");
			instance = null;
		}
		
		public static function sendNotification(notificationName:String, body:Object=null, type:String=null):void{
			IocAppFacade.getInstance().sendNotification(notificationName,body,type);
		}
	}
}